package com.vcc.boss.controller;


import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson2.JSONObject;
import com.mybatisflex.core.paginate.Page;
import com.vcc.boss.core.component.RedisComponent;
import com.vcc.core.annotations.RepeatSubmit;
import com.vcc.core.annotations.RestPack;
import com.vcc.core.exception.ProgramException;
import com.vcc.data.entity.BossUser;
import com.vcc.data.entity.CardType;
import com.vcc.service.boss.request.card.*;
import com.vcc.service.boss.response.card.CardStatisticsVo;
import com.vcc.service.boss.response.card.CardVoBoss;
import com.vcc.service.sa.BossUserUtil;
import com.vcc.service.service.*;
import jakarta.validation.constraints.NotBlank;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.List;

@RestController
@RequestMapping("bossCard")
public class CardController {

    @Autowired
    private CardTypeService cardService;
    @Autowired
    private BossUserService bossUserService;
    @Autowired
    private UserCardWalletService userCardWalletService;
    @Autowired
    private WalletService walletService;
    @Autowired
    private UserService userService;
    @Autowired
    private RedisComponent redisComponent;
    @Autowired
    private UserCardService userCardService;
    @Autowired
    private CardOrderService cardOrderService;
    @Autowired
    private TransactionService transactionService;


    @RestPack
    @SaCheckPermission(value = "card:list:create")
    @SaCheckLogin
    @PostMapping("addCard")
    @RepeatSubmit
    public Boolean addCard(
            @RequestBody @Validated BossCardTypeCreateRequest addCardDto
    ) {
        CardType card = cardService.addCardType(addCardDto);
        if (addCardDto.getType().equals("normal")) {
            // 普通卡开卡时创建钱包
            userCardWalletService.addCardInit(card, userService.listIds());
        } else {

        }
        return true;
    }


    @RestPack
    @SaCheckPermission(value = "card:list:view")
    @SaCheckLogin
    @GetMapping("paging")
    public Page<CardVoBoss> paging(
            Page<CardType> pageable,
            String channelName,
            String sectionNo,
            Integer status,
            String scenes,
            String type
    ) {
        Page<CardType> paging = cardService.paging(pageable, StpUtil.hasPermission("channel:view") ? channelName : null, sectionNo, status, scenes, type);
        return paging.map(it -> {
            String account = it.getOperationUserId() != null ? bossUserService.getUserNameById(it.getOperationUserId()) : "";
            if (!StpUtil.hasPermission("admin:card:list:admin:remark:view")) {
                it.setAdminRemark("");
            }
            if (!StpUtil.hasPermission("channel:view")) {
                it.setChannelName("");
            }
            return new CardVoBoss(it, account);
        });
    }

    @RestPack
    @SaCheckPermission(value = "card:list:view")
    @SaCheckLogin
    @GetMapping("listAll")
    public List<CardVoBoss> listAll(String sectionNo, String channelCode) {
        return cardService.listBySectionNoAndStatus(sectionNo, channelCode, 0).stream().map(it -> {
            String account = it.getOperationUserId() != null ? bossUserService.getUserNameById(it.getOperationUserId()) : "";
            if (!StpUtil.hasPermission("channel:view")) {
                it.setChannelName("");
            }
            return new CardVoBoss(it, account);
        }).toList();
    }

    @RestPack
    @SaCheckPermission(value = "card:list:view")
    @GetMapping("get")
    @SaCheckLogin
    public CardVoBoss get(
            Long id
    ) {
        CardType card = cardService.getById(id);
        String account = card.getOperationUserId() != null ? bossUserService.getUserNameById(card.getOperationUserId()) : "";
        return new CardVoBoss(card, account);
    }


    @RestPack
    @SaCheckPermission(value = "card:list:edit")
    @PostMapping("updateCardInfo")
    @RepeatSubmit
    public Boolean updateCardInfo(
            @RequestBody @Validated BossCardTypeUpdateRequest cardDto
    ) {
        return cardService.updateInfo(cardDto);
    }

    @RestPack
    @SaCheckPermission(value = "card:list:batch:edit")
    @PostMapping("batchUpdateCardInfo")
    @RepeatSubmit
    public Boolean batchUpdateCardInfo(
            @RequestBody @Validated BossCardTypeBatchUpdateRequest cardDto
    ) {

        return cardService.updateInfo(cardDto);
    }

    @RestPack
    @SaCheckPermission(value = "card:list:status:edit")
    @PostMapping("updateStatus")
    public Boolean updateStatus(
            @RequestBody @Validated BossCardTypeStatusUpdateRequest updateCardStatusDto
    ) {
        BossUser bossUser = BossUserUtil.get();
        if (!updateCardStatusDto.getStatus().equals(0) && !updateCardStatusDto.getStatus().equals(1)) {
            throw new ProgramException("状态值错误");
        }
        return cardService.updateStatus(updateCardStatusDto, bossUser.getId());
    }

    @RestPack
    @SaCheckPermission(value = "card:list:admin:remark:edit")
    @PostMapping("updateAdminRemark")
    @SaCheckLogin
    public Boolean updateAdminRemark(
            @RequestBody @Validated BossCardTypeRemarkUpdateRequest bossCardTypeRemarkUpdateRequest
    ) {
        BossUser bossUser = BossUserUtil.get();
        return cardService.updateAdminRemark(bossCardTypeRemarkUpdateRequest, bossUser.getId());
    }


    @RestPack
    @SaCheckPermission(value = "card:list:sort:edit")
    @PostMapping("updateSort")
    @SaCheckLogin
    public Boolean updateSort(
            @RequestBody @Validated BossCardTypeSortUpdateRequest bossCardTypeSortUpdateRequest
    ) {
        BossUser bossUser = BossUserUtil.get();
        return cardService.updateSort(bossCardTypeSortUpdateRequest, bossUser.getId());
    }


    @RestPack
    @SaCheckPermission(value = "card:list:sort:edit")
    @PostMapping("batchUpdateSort")
    @SaCheckLogin
    public Boolean batchUpdateSort(
            @RequestBody @Validated BossCardTypeSortBatchUpdateRequest updateCardSortDto
    ) {
        BossUser bossUser = BossUserUtil.get();
        return cardService.updateSort(updateCardSortDto, bossUser.getId());
    }


    @RestPack
    @SaCheckPermission(value = "card:statistics:view")
    @SaCheckLogin
    @GetMapping("statistics")
    @Validated
    public List<CardStatisticsVo> statistics(
            @RequestParam(value = "startDate") @NotBlank(message = "请选择开始时间") String startDate,
            @RequestParam(value = "endDate") @NotBlank(message = "请选择结束时间") String endDate,
            String channelName,
            String sectionNo
    ) {
        List<CardType> cardTypeList = cardService.listAll(
                StpUtil.hasPermission("channel:view") ? channelName : null,
                sectionNo
        );
        List<Long> cardTypeIds = cardTypeList.stream().map(CardType::getId).toList();
        DateTime start = DateUtil.parse(startDate, "yyyy-MM-dd");
        DateTime end = DateUtil.parse(endDate, "yyyy-MM-dd");
        List<JSONObject> userCardStatistics = userCardService.cardTypeStatistics(start, end, cardTypeIds);
        List<JSONObject> cardOrderStatistics = cardOrderService.cardTypeStatistics(start, end, cardTypeIds);
        List<JSONObject> transactionStatistics = transactionService.cardTypeStatistics(start, end, cardTypeIds);
        return cardTypeList.stream().map(it -> {
            JSONObject userCardInfo = userCardStatistics.stream().filter(temp -> temp.getLong("cardTypeId").equals(it.getId())).findFirst().orElse(null);
            JSONObject cardOrderInfo = cardOrderStatistics.stream().filter(temp -> temp.getLong("cardTypeId").equals(it.getId())).findFirst().orElse(null);
            JSONObject transaction = transactionStatistics.stream().filter(temp -> temp.getLong("cardTypeId").equals(it.getId())).findFirst().orElse(null);
            return CardStatisticsVo.builder()
                    .cardTypeId(it.getId())
                    .sectionNo(it.getSectionNo())
                    .channelName(it.getChannelName())
                    .openCardCount(cardOrderInfo == null ? 0 : cardOrderInfo.getIntValue("openCount"))
                    .rechargeCount(cardOrderInfo == null ? 0 : cardOrderInfo.getIntValue("rechargeCount"))
                    .rechargeAmount(cardOrderInfo == null ? BigDecimal.ZERO : cardOrderInfo.getBigDecimal("rechargeAmount"))
                    .withdrawCount(cardOrderInfo == null ? 0 : cardOrderInfo.getIntValue("withdrawCount"))
                    .withdrawAmount(cardOrderInfo == null ? BigDecimal.ZERO : cardOrderInfo.getBigDecimal("withdrawAmount"))
                    .closeCardCount(cardOrderInfo == null ? 0 : cardOrderInfo.getIntValue("closeCount"))
                    .totalCount(userCardInfo == null ? 0 : userCardInfo.getIntValue("cardCount"))
                    .activeCount(userCardInfo == null ? 0 : userCardInfo.getIntValue("activeCount"))
                    .blockedCount(userCardInfo == null ? 0 : userCardInfo.getIntValue("blockedCount"))
                    .closeCount(userCardInfo == null ? 0 : userCardInfo.getIntValue("closedCount"))
                    .controlCount(userCardInfo == null ? 0 : userCardInfo.getIntValue("controlCount"))
                    .sumBalance(userCardInfo == null ? BigDecimal.ZERO : userCardInfo.getBigDecimal("usableQuotaSum"))
                    .cardConsumeAmount(transaction == null ? BigDecimal.ZERO : transaction.getBigDecimal("sumAmount"))
                    .cardConsumeSuccessAmount(transaction == null ? BigDecimal.ZERO : transaction.getBigDecimal("successAuthAmount"))
                    .cardConsumeFailAmount(transaction == null ? BigDecimal.ZERO : transaction.getBigDecimal("failedAuthAmount"))
                    .cardConsumeCount(transaction == null ? 0 : transaction.getIntValue("sumCount"))
                    .cardConsumeSuccessCount(transaction == null ? 0 : transaction.getIntValue("successAuthCount"))
                    .cardConsumeFailCount(transaction == null ? 0 : transaction.getIntValue("failedAuthCount"))
                    .cardRefundAmount(transaction == null ? BigDecimal.ZERO : transaction.getBigDecimal("refundAmount"))
                    .cardRefundCount(transaction == null ? 0 : transaction.getIntValue("refundCount"))
                    .cardReversalAmount(transaction == null ? BigDecimal.ZERO : transaction.getBigDecimal("reversalAmount"))
                    .cardReversalCount(transaction == null ? 0 : transaction.getIntValue("reversalCount"))
                    .verifyCount(transaction == null ? 0 : transaction.getIntValue("verifyCount"))
                    .build();
        }).toList();
    }


}
